/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.commons.exception.service;

import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import io.iec.edp.caf.commons.exception.config.ExceptionConfigManager;
import io.iec.edp.caf.commons.exception.config.ExceptionHandlingSettings;
import io.iec.edp.caf.commons.exception.core.ExceptionUtility;
import io.iec.edp.caf.commons.exception.entity.*;
import io.iec.edp.caf.commons.exception.logger.ExceptionInnerLogger;

import java.util.List;

/**
 * @author Leon Huo
 * @Date: 2021/4/25
 */
public class CafExceptionHandler {
    private ExceptionConfigManager manager;

    public CafExceptionHandler(ExceptionHandlingSettings settings, List<ExceptionHandlerInfo> handlerInfoList,
                               List<ExceptionPolicyInfo> policyInfoList) {
        this.manager = new ExceptionConfigManager(settings, handlerInfoList, policyInfoList);
    }

    /**
     * 服务端处理错误信息
     *
     * @param exceptionContext 待处理的异常上下文
     */
    public Exception handle(ExceptionContext exceptionContext) {
        //获取国际化消息
        buildExceptionI18nMessage(exceptionContext.getException());
        ExceptionHandlerInfo handlerInfo = null;
        try {
            //未传入策略名称，则调用默认的异常处理策略
            if (exceptionContext.getPolicyName() == null || "".equals(exceptionContext.getPolicyName())) {
                String defaultHandlerName = this.manager.getDefaultPolicyName();
                //默认策略名称不存在，抛出异常
                if (defaultHandlerName == null || "".equals(defaultHandlerName)) {
                    String message = ExceptionUtility.getExceptionInnerMessage(ExceptionErrorCode.defaultHandleIsNull);
                    throw new CafExceptionHandleException("caf", ExceptionErrorCode.defaultHandleIsNull, message, exceptionContext.getException());
                }
                exceptionContext.setPolicyName(defaultHandlerName);
            }
            //根据策略名称获得异常处理策略
            ExceptionPolicyInfo policyData = this.manager.getExceptionPolicyInfo(exceptionContext.getPolicyName());
            //异常策略不存在，抛出异常
            if (policyData == null) {
                String message = ExceptionUtility.getExceptionInnerMessage(ExceptionErrorCode.exceptionHandleIsNull);
                throw new CafExceptionHandleException("caf", ExceptionErrorCode.exceptionHandleIsNull, message, exceptionContext.getException());
            }

            //根据policyInfo获取handler来处理
            handlerInfo = this.manager.getExceptionHandlerInfo(policyData.getHandlerList());
            if (handlerInfo == null) {
                String message = ExceptionUtility.getExceptionInnerMessage(ExceptionErrorCode.exceptionHandleIsNull);
                throw new CafExceptionHandleException("caf", ExceptionErrorCode.exceptionHandleIsNull, message, exceptionContext.getException());
            }
            return ExceptionHandlerEntry.getCurrent().excuteDefaultExceptionHandler(exceptionContext, handlerInfo);
        } catch (Exception e) {
            try {
                //执行默认操作，然后抛出异常
                ExceptionHandlerEntry.getCurrent().excuteDefaultExceptionHandler(exceptionContext, handlerInfo);
            } catch (Exception e2) {
                //默认操作出错，自己记录日志
                ExceptionInnerLogger.writeLog(exceptionContext.getException(), "");
                ExceptionInnerLogger.writeLog(e, "");
                ExceptionInnerLogger.writeLog(e2, "");
                String message = ExceptionUtility.getExceptionInnerMessage(ExceptionErrorCode.exceptionHandleError);
                throw new CafExceptionHandleException("caf", ExceptionErrorCode.exceptionHandleError, message, e2);
            }
            if (e instanceof CafExceptionHandleException)
                throw e;
            String message = ExceptionUtility.getExceptionInnerMessage(ExceptionErrorCode.exceptionHandleError);
            throw new CafExceptionHandleException("caf", ExceptionErrorCode.exceptionHandleError, message, e);
        }

    }

    /**
     * 处理异常，以默认的处理上下文处理
     *
     * @param cafRuntimeException
     * @param policyName
     */
    public Exception handle(CAFRuntimeException cafRuntimeException, String policyName) {
        if (cafRuntimeException == null)
            return null;
        ExceptionContext context = new ExceptionContext(cafRuntimeException, policyName);
        return handle(context);
    }

    /**
     * 异常的国际化信息赋值
     *
     * @param exception 异常类
     */
    private void buildExceptionI18nMessage(Exception exception) {
        String i18nMessage = null;

        //获取内部异常
        Throwable innerException = exception;
        while (innerException != null) {
            try {
                if (innerException instanceof CAFRuntimeException)
                    i18nMessage = ((CAFRuntimeException) innerException).getI18nMessage();
            } catch (Exception e) {
                //异常吞掉，继续执行
            } finally {
                innerException = innerException.getCause();
            }
        }
    }
}
